package bma.common.langutil.ai.common;

import java.util.Iterator;

import bma.common.langutil.ai.AIUtil;
import bma.common.langutil.ai.stack.AIStack;
import bma.common.langutil.ai.stack.AIStackSimple;
import bma.common.langutil.core.Preconditions;

/**
 * 
 * @author guanzhong
 * @since 1.0 (imported from BMA.ESP Project)
 * 
 * @param <ITEM_TYPE>
 */
public abstract class AIIteratorPage<ITEM_TYPE> implements
		AIIterator<ITEM_TYPE> {

	private Iterator<ITEM_TYPE> current;

	public AIIteratorPage() {
		super();
	}

	public AIIteratorPage(Iterator<ITEM_TYPE> iter) {
		super();
		this.current = iter;
	}

	public Iterator<ITEM_TYPE> getCurrent() {
		return current;
	}

	public void setCurrent(Iterator<ITEM_TYPE> v) {
		this.current = v;
	}

	protected abstract boolean nextPage(AIStack<Iterator<ITEM_TYPE>> stack);

	@Override
	public boolean hasNext(final AIStack<Boolean> stack) {
		if (this.current != null) {
			if (current.hasNext()) {
				return stack.success(true);
			}
			current = null;
		}
		AIStackSimple<Iterator<ITEM_TYPE>> s = new AIStackSimple<Iterator<ITEM_TYPE>>(
				stack);
		nextPage(s);
		return s.callback(AIUtil.callback(stack,
				new AIResultHandler<Iterator<ITEM_TYPE>>() {

					@Override
					public void success(Iterator<ITEM_TYPE> cur) {
						if (cur == null) {
							stack.success(false);
							return;
						}
						if (!cur.hasNext()) {
							stack.success(false);
						}
						current = cur;
						stack.success(true);
					}
				}));
	}

	@Override
	public boolean next(AIStack<ITEM_TYPE> stack) {
		Preconditions.checkNotNull(current);
		return stack.success(current.next());
	}

}
